package cn.sangedon.review.data.spider.impl;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.sangedon.review.common.constant.TimeConstant;
import cn.sangedon.review.common.domain.data.SpiderMateData;
import cn.sangedon.review.common.domain.data.StockDayInfo;
import cn.sangedon.review.common.service.data.StockDayInfoService;
import cn.sangedon.review.data.constant.SpiderEnum;
import cn.sangedon.review.data.spider.AbstractStockInfoSpider;
import cn.sangedon.review.data.utils.SpiderUtil;
import com.alibaba.fastjson.JSONObject;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 深圳日交易历史数据Excel数据爬虫
 * Excel数据可一次性获取当日所有交易数据，时间范围可获取三天内
 *
 * @author dongliangqiong
 */
@Slf4j
@Component
public class HistoryStockInfoExcelSzSpider extends AbstractStockInfoSpider {
    @Autowired
    private StockDayInfoService stockDayInfoService;

    @Override
    public void runJob(List<SpiderMateData> spiderMateDataList) {
        spiderMateDataList.stream().filter(e -> e.getSpiderName().equals(SpiderEnum.SZ_DAILY_HISTORY_EXCEL_HTTP.getName())).findFirst()
                          .ifPresent(e -> {
                              addSchedule(e);
                          });
    }

    @Override
    public void crawlData() {
        log.info("开始获取深圳交易所日交易历史Excel数据");
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        JSONObject jsonObject = JSONObject.parseObject(getSpiderMateData().getSpiderParam());
        Long endTime = jsonObject.getLong("largeTime");
        Long minTime = jsonObject.getLong("minTime");
        Long startTime = endTime - TimeConstant.ONE_DAY_MILLIS * 2;
        while (endTime > minTime) {
            processData(startTime, endTime, df);
            endTime = startTime - TimeConstant.ONE_DAY_MILLIS;
            startTime = endTime - TimeConstant.ONE_DAY_MILLIS * 2;
        }
    }

    private void processData(Long startTime, Long endTime, DateFormat df) {
        AtomicInteger index = new AtomicInteger(0);
        while (index.getAndIncrement() < 3) {
            try {
                long preTime = System.currentTimeMillis();
                String start = df.format(new Date(startTime));
                String end = df.format(new Date(endTime));
                log.info("第{}次开始获取 {} ～ {}日深交所日交易历史Excel数据", index.intValue(), start, end);
                String spiderUrl = String.format(getSpiderMateData().getSpiderUrl(), start, end);
                HttpResponse response = HttpRequest.get(spiderUrl).header("Content-Type",
                                                                          "application/vnd.openxmlformats-officedocument.spreadsheetml" +
                                                                          ".sheet;" + "charset=GBK").execute();

                InputStream inputStream = response.bodyStream();
                ExcelReader reader = ExcelUtil.getReader(inputStream);
                List<Map<String, Object>> maps = reader.readAll();
                List<StockDayInfo> list = new ArrayList<>();
                for (Map<String, Object> map : maps) {
                    StockDayInfo stockDayInfo = new StockDayInfo();
                    stockDayInfo.setName(map.get("证券简称").toString());
                    stockDayInfo.setCode(map.get("证券代码").toString());
                    stockDayInfo.setClosingPrice(new BigDecimal(map.get("今收").toString().replace(",", "")));
                    stockDayInfo.setOpeningPrice(new BigDecimal(map.get("开盘").toString().replace(",", "")));
                    stockDayInfo.setBottomPrice(new BigDecimal(map.get("最低").toString().replace(",", "")));
                    stockDayInfo.setPeakPrice(new BigDecimal(map.get("最高").toString().replace(",", "")));
                    stockDayInfo.setChangeRate(new BigDecimal(map.get("涨跌幅（%）").toString().replace(",", "")));
                    stockDayInfo.setTradingDate(map.get("交易日期").toString());
                    stockDayInfo.setTradingAmount(new BigDecimal(map.get("成交金额(万元)").toString().replace(",", "")));
                    stockDayInfo.setTradingVolume(
                        new BigDecimal(map.get("成交量(万)").toString().replace(",", "")).multiply(new BigDecimal(100)));
                    stockDayInfo.setChangeAmount(stockDayInfo.getClosingPrice().subtract(stockDayInfo.getOpeningPrice()));
                    list.add(stockDayInfo);
                }
                stockDayInfoService.saveOrUpdateBatch(list);
                log.info("{} ～ {}日,深交所日交易历史数据保存成功:{}", start, end, list.size());

                index.set(3);
                Long cost = System.currentTimeMillis() - preTime;
                if (cost < 2000) {
                    SpiderUtil.randomDelay();
                }
                log.info("爬取深圳市日交易数据历史Excel耗时:{}", cost);
            } catch (Exception e) {
                log.error("爬取深圳市日交易数据历史Excel失败:{}", e);
            }
        }
    }
}
